/// \file
/// \ingroup tutorial_math
/// \notebook -nodraw
/// Performance test of all the ROOT random generator (TRandom, TRandom1, TRandom2 and TRandom3)
/// Tests the generator TRandom3 against some ref values
/// and creates a timing table against TRandom, TRandom1 and TRandom2.
///
/// E.g. on an an Intel Xeon Quad-core Harpertown (E5410) 2.33 GHz running
/// Linux SLC4 64 bit and compiled with gcc 3.4
///
/// ~~~
/// Distribution        nanoseconds/call
///                     TRandom  TRandom1 TRandom2 TRandom3
/// Rndm..............    5.000  105.000    7.000   10.000
/// RndmArray.........    4.000  104.000    6.000    9.000
/// Gaus..............   36.000  180.000   40.000   48.000
/// Rannor............  118.000  220.000  120.000  124.000
/// Landau............   22.000  123.000   26.000   31.000
/// Exponential.......   93.000  198.000   98.000  104.000
/// Binomial(5,0.5)...   30.000  548.000   46.000   65.000
/// Binomial(15,0.5)..   75.000 1615.000  125.000  178.000
/// Poisson(3)........   96.000  494.000  109.000  125.000
/// Poisson(10).......  138.000 1236.000  165.000  203.000
/// Poisson(70).......  818.000 1195.000  835.000  844.000
/// Poisson(100)......  837.000 1218.000  849.000  864.000
/// GausTF1...........   83.000  180.000   87.000   88.000
/// LandauTF1.........   80.000  180.000   83.000   86.000
/// GausUNURAN........   40.000  139.000   41.000   44.000
/// PoissonUNURAN(10).   85.000  271.000   92.000  102.000
/// PoissonUNURAN(100)   62.000  256.000   69.000   78.000
/// ~~~
///
/// Note that this tutorial can be executed in interpreted or compiled mode
///
/// ~~~{.cpp}
///  Root > .x testrandom.C
///  Root > .x testrandom.C++
/// ~~~
///
/// \macro_output
/// \macro_code
///
/// \authors Rene Brun, Lorenzo Moneta

#include <TRandom1.h>
#include <TRandom2.h>
#include <TRandom3.h>
#include <TRandomGen.h>
#include <TStopwatch.h>
#include <TF1.h>
#if __has_include("TUnuran.h") // handy check
#include <TUnuran.h>
#include <TUnuranContDist.h>
#endif
#include <TFile.h>


void testAll() {
  int i, N = 2000000;
  float cpn = 1000000000./N;
  int N1 = N/10; float cpn1 = cpn*10;  // for TRandom1
  double x,y;
  TRandom *rsave = gRandom;
  TRandom *r0 = new TRandom();
  TRandom *r1 = new TRandom1();
  TRandom *r2 = new TRandom2();
  TRandom *r3 = new TRandom3();
  TRandom *r4 = new TRandomMixMax();
  TRandom *r5 = new TRandomMixMax17();
  TRandom *r6 = new TRandomGen<ROOT::Math::MixMaxEngine<256,0>>();
  TRandom *r7 = new TRandomMixMax256();
  TRandom *r8 = new TRandomGen<ROOT::Math::MixMaxEngine<256,4>>();
  TRandom *r9 = new TRandomMT64();
  TRandom *r10 = new TRandomRanlux48();


  TStopwatch sw;
  printf("Distribution            nanoseconds/call\n");
  printf("                    TRandom  TRandom1 TRandom2 TRandom3 MixMax240 MixMax17 Mixmax256_0 MixMax256_2 MixMax256_4 MT_64 Ranlux48\n");

  sw.Start();
  for (i=0;i<N;i++) {
     x = r0->Rndm(i);
  }
  printf("Rndm.............. %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N1;i++) {
     x = r1->Rndm(i);
  }
  printf(" %8.3f",sw.CpuTime()*cpn1);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r2->Rndm(i);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r3->Rndm(i);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  // new random generators

  sw.Start();
  for (i=0;i<N;i++) {
     x = r4->Rndm(i);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);

  sw.Start();
  for (i=0;i<N;i++) {
     x = r5->Rndm(i);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);

  sw.Start();
  for (i=0;i<N;i++) {
     x = r6->Rndm(i);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);

  sw.Start();
  for (i=0;i<N;i++) {
     x = r7->Rndm(i);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);

  sw.Start();
  for (i=0;i<N;i++) {
     x = r8->Rndm(i);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);

  sw.Start();
  for (i=0;i<N;i++) {
     x = r9->Rndm(i);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  
  sw.Start();
  for (i=0;i<N1;i++) {
     x = r10->Rndm(i);
  }
  printf(" %8.3f",sw.CpuTime()*cpn1);

  printf("\n\n");

  // RNDMARRAY
  
  const int NR = 1000;
  double rn[NR];
  sw.Start();
  for (i=0;i<N;i+=NR) {
     r0->RndmArray(NR,rn);
  }
  printf("RndmArray......... %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N1;i+=NR) {
     r1->RndmArray(NR,rn);
  }
  printf(" %8.3f",sw.CpuTime()*cpn1);
  sw.Start();
  for (i=0;i<N;i+=NR) {
     r2->RndmArray(NR,rn);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i+=NR) {
     r3->RndmArray(NR,rn);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
   sw.Start();
  for (i=0;i<N;i+=NR) {
     r4->RndmArray(NR,rn);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i+=NR) {
     r5->RndmArray(NR,rn);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i+=NR) {
     r6->RndmArray(NR,rn);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i+=NR) {
     r7->RndmArray(NR,rn);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i+=NR) {
     r8->RndmArray(NR,rn);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i+=NR) {
     r9->RndmArray(NR,rn);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N1;i+=NR) {
     r10->RndmArray(NR,rn);
  }
  printf(" %8.3f\n",sw.CpuTime()*cpn1);

  // Gaus

  sw.Start();
  for (i=0;i<N;i++) {
     x = r0->Gaus(0,1);
  }
  printf("Gaus.............. %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N1;i++) {
     x = r1->Gaus(0,1);
  }
  printf(" %8.3f",sw.CpuTime()*cpn1);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r2->Gaus(0,1);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r3->Gaus(0,1);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r4->Gaus(0,1);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r5->Gaus(0,1);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r6->Gaus(0,1);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r7->Gaus(0,1);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r8->Gaus(0,1);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r9->Gaus(0,1);
  }
  printf(" %8.3f\n",sw.CpuTime()*cpn);


  // RANNOR
  
  sw.Start();
  for (i=0;i<N;i+=2) {
     r0->Rannor(x,y);
  }
  printf("Rannor............ %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N1;i+=2) {
     r1->Rannor(x,y);
  }
  printf(" %8.3f",sw.CpuTime()*cpn1);
  sw.Start();
  for (i=0;i<N;i+=2) {
     r2->Rannor(x,y);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i+=2) {
     r3->Rannor(x,y);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i+=2) {
     r4->Rannor(x,y);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i+=2) {
     r5->Rannor(x,y);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i+=2) {
     r6->Rannor(x,y);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i+=2) {
     r7->Rannor(x,y);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i+=2) {
     r8->Rannor(x,y);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i+=2) {
     r9->Rannor(x,y);
  }
  printf(" %8.3f\n",sw.CpuTime()*cpn);
  
  // Landau
  
  sw.Start();
  for (i=0;i<N;i++) {
     x = r0->Landau(0,1);
  }
  printf("Landau............ %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N1;i++) {
     x = r1->Landau(0,1);
  }
  printf(" %8.3f",sw.CpuTime()*cpn1);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r2->Landau(0,1);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r3->Landau(0,1);
  }
  printf(" %8.3f\n",sw.CpuTime()*cpn);

  sw.Start();
  for (i=0;i<N;i++) {
     x = r0->Exp(1);
  }
  printf("Exponential....... %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N1;i++) {
     x = r1->Exp(1);
  }
  printf(" %8.3f",sw.CpuTime()*cpn1);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r2->Exp(1);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r3->Exp(1);
  }
  printf(" %8.3f\n",sw.CpuTime()*cpn);

  sw.Start();
  for (i=0;i<N;i++) {
     x = r0->Binomial(5,0.5);
  }
  printf("Binomial(5,0.5)... %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N1;i++) {
     x = r1->Binomial(5,0.5);
  }
  printf(" %8.3f",sw.CpuTime()*cpn1);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r2->Binomial(5,0.5);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r3->Binomial(5,0.5);
  }
  printf(" %8.3f\n",sw.CpuTime()*cpn);

  sw.Start();
  for (i=0;i<N;i++) {
     x = r0->Binomial(15,0.5);
  }
  printf("Binomial(15,0.5).. %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N1;i++) {
     x = r1->Binomial(15,0.5);
  }
  printf(" %8.3f",sw.CpuTime()*cpn1);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r2->Binomial(15,0.5);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r3->Binomial(15,0.5);
  }
  printf(" %8.3f\n",sw.CpuTime()*cpn);

  sw.Start();
  for (i=0;i<N;i++) {
     x = r0->Poisson(3);
  }
  printf("Poisson(3)........ %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N1;i++) {
     x = r1->Poisson(3);
  }
  printf(" %8.3f",sw.CpuTime()*cpn1);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r2->Poisson(3);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r3->Poisson(3);
  }
  printf(" %8.3f\n",sw.CpuTime()*cpn);

  sw.Start();
  for (i=0;i<N;i++) {
     x = r0->Poisson(10);
  }
  printf("Poisson(10)....... %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N1;i++) {
     x = r1->Poisson(10);
  }
  printf(" %8.3f",sw.CpuTime()*cpn1);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r2->Poisson(10);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r3->Poisson(10);
  }
  printf(" %8.3f\n",sw.CpuTime()*cpn);

  sw.Start();
  for (i=0;i<N;i++) {
     x = r0->Poisson(70);
  }
  printf("Poisson(70)....... %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N1;i++) {
     x = r1->Poisson(70);
  }
  printf(" %8.3f",sw.CpuTime()*cpn1);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r2->Poisson(70);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r3->Poisson(70);
  }
  printf(" %8.3f\n",sw.CpuTime()*cpn);

  sw.Start();
  for (i=0;i<N;i++) {
     x = r0->Poisson(100);
  }
  printf("Poisson(100)...... %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N1;i++) {
     x = r1->Poisson(100);
  }
  printf(" %8.3f",sw.CpuTime()*cpn1);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r2->Poisson(100);
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = r3->Poisson(100);
  }
  printf(" %8.3f\n",sw.CpuTime()*cpn);

  TF1 *f1 = new TF1("f1","gaus",-4,4);
  f1->SetParameters(1,0,1);
  gRandom = r0;
  sw.Start();
  for (i=0;i<N;i++) {
     x = f1->GetRandom();
  }
  printf("GausTF1........... %8.3f",sw.CpuTime()*cpn);
  gRandom = r1;
  sw.Start();
  for (i=0;i<N;i++) {
     x = f1->GetRandom();
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  gRandom = r2;
  sw.Start();
  for (i=0;i<N;i++) {
     x = f1->GetRandom();
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  gRandom = r3;
  sw.Start();
  for (i=0;i<N;i++) {
     x = f1->GetRandom();
  }
  printf(" %8.3f\n",sw.CpuTime()*cpn);

  TF1 *f2 = new TF1("f2","landau",-5,15);
  f2->SetParameters(1,0,1);

  gRandom = r0;
  sw.Start();
  for (i=0;i<N;i++) {
     x = f2->GetRandom();
  }
  printf("LandauTF1......... %8.3f",sw.CpuTime()*cpn);
  gRandom = r1;
  sw.Start();
  for (i=0;i<N;i++) {
     x = f2->GetRandom();
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  gRandom = r2;
  sw.Start();
  for (i=0;i<N;i++) {
     x = f2->GetRandom();
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  gRandom = r3;
  sw.Start();
  for (i=0;i<N;i++) {
     x = f2->GetRandom();
  }
  printf(" %8.3f\n",sw.CpuTime()*cpn);

  // test using Unuran
#if __has_include("TUnuran.h")
  TUnuran unr0(r0);
  TUnuran unr1(r1);
  TUnuran unr2(r2);
  TUnuran unr3(r3);

  // continuous distribution (ex. Gaus)
  TUnuranContDist dist(f1);
  // use arou method (is probably the fastest)
  unr0.Init(dist,"arou");
  unr1.Init(dist,"arou");
  unr2.Init(dist,"arou");
  unr3.Init(dist,"arou");

  sw.Start();
  for (i=0;i<N;i++) {
     x = unr0.Sample();
  }
  printf("GausUNURAN........ %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = unr1.Sample();
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = unr2.Sample();
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = unr3.Sample();
  }
  printf(" %8.3f\n",sw.CpuTime()*cpn);

  // Poisson (nned to initialize before with Poisson mu value)

  unr0.InitPoisson(10);
  unr1.InitPoisson(10);
  unr2.InitPoisson(10);
  unr3.InitPoisson(10);

  sw.Start();
  for (i=0;i<N;i++) {
     x = unr0.SampleDiscr();
  }
  printf("PoissonUNURAN(10). %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = unr1.SampleDiscr();
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = unr2.SampleDiscr();
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = unr3.SampleDiscr();
  }
  printf(" %8.3f\n",sw.CpuTime()*cpn);

  unr0.InitPoisson(100);
  unr1.InitPoisson(100);
  unr2.InitPoisson(100);
  unr3.InitPoisson(100);

  sw.Start();
  for (i=0;i<N;i++) {
     x = unr0.SampleDiscr();
  }
  printf("PoissonUNURAN(100) %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = unr1.SampleDiscr();
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = unr2.SampleDiscr();
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = unr3.SampleDiscr();
  }
  printf(" %8.3f\n",sw.CpuTime()*cpn);
#endif

  delete r0;
  delete r1;
  delete r2;
  delete r3;
  delete r4;
  delete r5;
  delete r6;
  delete r7;
  delete r8;
  delete r9;
  delete r10;
  gRandom = rsave;

#ifdef LATER
#if __has_include("TUnuran.h")
  // Binomial
  unr0.InitBinomial(15,0.5);
  unr1.InitBinomial(15,0.5);
  unr2.InitBinomial(15,0.5);
  unr3.InitBinomial(15,0.5);

  sw.Start();
  for (i=0;i<N;i++) {
     x = unr0.SampleDiscr();
  }
  printf("BinomialUN(15,0.5) %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = unr1.SampleDiscr();
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = unr2.SampleDiscr();
  }
  printf(" %8.3f",sw.CpuTime()*cpn);
  sw.Start();
  for (i=0;i<N;i++) {
     x = unr3.SampleDiscr();
  }
  printf(" %8.3f\n",sw.CpuTime()*cpn);
#endif
#endif

}

int testRandom3() {

  Float_t RefValue[] = // running using a seed of 4357 ROOT 5.13.07 and checked with GSL 1.8
     {  0.999741749, 0.162909875, 0.282617805, 0.947201082, 0.231656543, 0.484973614, 0.957476957, 0.744305343,
        0.540043658, 0.739952981, 0.759943798, 0.658636614, 0.315637622, 0.804403015, 0.519672115, 0.168572422,
        0.47552973, 0.392313994, 0.221667687, 0.213190459,0.0303352042,  0.33353925, 0.194148851, 0.943716781,
        0.579931675, 0.898304858, 0.665563931,  0.49861031, 0.560628257, 0.182284646, 0.296525531, 0.117408933,
        0.0629176658, 0.648125575, 0.725418529, 0.637131158, 0.713885062,0.0995762432, 0.699267196,  0.10781247,
        0.129242751, 0.502403039, 0.207779906, 0.288910306,0.0831747944, 0.128124215, 0.547371411,0.0823195996,
        0.292141427, 0.891623737, 0.227117839, 0.431845463, 0.140733001, 0.400392135, 0.686946901, 0.170670911,
        0.440820868, 0.045336565, 0.311296414, 0.506181051,  0.18241084, 0.511032015, 0.740788205, 0.365988627,
        0.160808837, 0.460106785, 0.627836472, 0.677603688, 0.698196523, 0.478536868,0.0901075942, 0.338728522,
        0.0952137967, 0.436541964, 0.474673352, 0.419245926, 0.777536852, 0.624610565,  0.98043655, 0.370430201,
        0.830812636, 0.140806447, 0.744085307,  0.82973968, 0.391104318, 0.621956392, 0.346699478,0.0461695245,
        0.613066321, 0.567374048, 0.498894026, 0.723802079, 0.144550525,0.0423031633, 0.310787023, 0.121641154,
        0.242069671, 0.381058855, 0.440128537, 0.599795902, 0.644574654, 0.432626217, 0.555968262, 0.716841168,
        0.642362515, 0.685776725,0.0961581462, 0.122933464,0.0569974151, 0.820072044, 0.125539286, 0.315745071,
        0.180566925, 0.142227219, 0.664429613, 0.685189223, 0.191001933, 0.436343019, 0.964459225,  0.86816359,
        0.130879965,  0.48444228, 0.374654451, 0.900475122, 0.178656787, 0.679635131,  0.62287431,  0.98365595,
        0.44071478, 0.804737277, 0.994845061, 0.541550961, 0.255905455, 0.638945635,  0.57591027,  0.25872142,
        0.191593001, 0.445663047, 0.149266509, 0.996723689, 0.121762222,  0.65153928,0.0277950978, 0.389977602,
        0.827913044, 0.283813907, 0.610203644,  0.23641275,  0.41082105, 0.677714617, 0.847126588, 0.649256228,
        0.0813826511, 0.120830484, 0.479199264, 0.777878358, 0.471977701, 0.943337511, 0.980800992, 0.334554731,
        0.202667924, 0.342841234, 0.653544244, 0.682758797,  0.60993614,0.0999271029, 0.766254981, 0.735581528,
        0.24113914, 0.263178711, 0.960869899, 0.423395737, 0.336058146,0.000249497825, 0.868841017,0.00375315035,
        0.165846311,0.0118208411, 0.606455074, 0.729972019, 0.613824557, 0.965768184, 0.497098261, 0.529885403,
        0.461607532, 0.713033701, 0.579959768, 0.682802555, 0.953921514,0.0236552036, 0.280110147, 0.869526353,
        0.299333274, 0.319553603, 0.300951709, 0.941111486, 0.848127064, 0.753346129, 0.538244087, 0.408481381,
        0.212371316,0.0761404021, 0.289934908,0.0197818337, 0.241247899, 0.384619165, 0.454906886, 0.373982521,
        0.440188796, 0.117896808, 0.805429845, 0.164892641, 0.282529936, 0.172685399,  0.93584233,  0.68095306,
        0.133696739, 0.254761223, 0.399444876, 0.369235365, 0.726361892, 0.277837459, 0.693569104, 0.500354689,
        0.118405538, 0.151303335, 0.681446943, 0.720665918, 0.979646939, 0.696779111, 0.557210072, 0.680821482,
        0.95535205, 0.598208956, 0.770453895, 0.913597486, 0.658958649, 0.670974613, 0.578185175,  0.95303929,
        0.162923458, 0.335056986, 0.951824704, 0.109661644, 0.619302303, 0.956816742, 0.985243094,0.0707377489,
        0.50233039, 0.680721226, 0.553320066, 0.587005581, 0.691620562,  0.46264791, 0.574254294, 0.072890088,
        0.638266518, 0.387757288, 0.220960217,0.00223180233, 0.495656775, 0.191316523, 0.022265008, 0.903589021,
        0.738628175,  0.44453089, 0.417702243, 0.760861122, 0.437753222, 0.190982861, 0.577112962, 0.132688343,
        0.317824347,  0.48691649, 0.939091069, 0.933946281, 0.073660135, 0.612436295, 0.514748724, 0.624663582,
        0.130645262, 0.645210441,  0.13414855, 0.652925968, 0.265210009, 0.381805269,  0.59021506, 0.669704082,
        0.55433248,0.0195047602, 0.184346962, 0.991180462, 0.573677764, 0.637762085, 0.594857598, 0.515244688,
        0.330693509,  0.39674245,  0.88396548, 0.771485266, 0.599075381,0.0247266297,0.0122587895, 0.698452319,
        0.265991009, 0.736700721, 0.999972619, 0.749792316, 0.484955589, 0.823700529,  0.62277709, 0.902512094,
        0.0565051287, 0.739077389,  0.37617622, 0.036800765, 0.776198219, 0.837354186,  0.34508193,0.0818426476,
        0.222621545, 0.152476319, 0.401177195, 0.531612608, 0.811706602,0.0407775661, 0.117889008, 0.575189965,
        0.832362208, 0.204641853, 0.238721773,   0.9969287, 0.258590596, 0.892055968, 0.846859788, 0.306583706,
        0.0333624918, 0.706420498, 0.193615608, 0.508978138,0.0215451468, 0.672732793, 0.813562444, 0.807284052,
        0.481526843, 0.537519095, 0.780848606, 0.335848908, 0.699259371, 0.425855299, 0.825240663, 0.945613692,
        0.55484125, 0.710495188, 0.378360366, 0.648338731,0.0456727168, 0.155477323, 0.885353968, 0.721565725,
        0.961667201, 0.430300885, 0.132031354, 0.439331209, 0.467187736, 0.410083217, 0.277196711, 0.278509559,
        0.954620806, 0.804357491, 0.968510466, 0.999722791, 0.947160283, 0.248551138,0.0067049861, 0.444727315,
        0.674048778, 0.496480361,0.0210092501, 0.831763222, 0.108545852,0.0931516394,  0.89020564, 0.445945211,
        0.906906768, 0.554039821, 0.759434349, 0.815551384, 0.532968503,0.0551351462,0.0539856541,  0.89918819,
        0.146907374, 0.482647314,0.0673029809, 0.281161865, 0.932849165, 0.507317933, 0.564503014,   0.8007132,
        0.645887499, 0.309219498,0.0478066066,  0.25196583, 0.713881142, 0.670994017,  0.60528576, 0.148271899,
        0.79525035, 0.665277353, 0.854302043, 0.810533677,0.0711439839,0.0687935678, 0.890466573, 0.758045957,
        0.0703105873, 0.852094478, 0.775356902, 0.684895203, 0.234552787, 0.461575694, 0.936435457, 0.664946419,
        0.45967959,  0.88782351, 0.574622261,0.0301686234, 0.767354721, 0.345478555, 0.609123143,  0.21754287,
        0.643760561, 0.571392649, 0.802311049, 0.962335547, 0.401769856, 0.996553418, 0.745945812, 0.448411183,
        0.39578428, 0.123389926, 0.532614913, 0.833379602,  0.91767313, 0.825607567,   0.4459154, 0.267136201,
        0.6643989, 0.766860694, 0.665968275, 0.503955105, 0.835153702, 0.622405379, 0.457538918, 0.554983278,
        0.36581371, 0.656302231, 0.917038669, 0.276054591, 0.121214441, 0.966178254, 0.697439008, 0.443547789,
        0.630195824, 0.368346675, 0.238191956, 0.300273821, 0.710332172,0.0474748381, 0.492525443,0.0812539798,
        0.122016782,  0.99310218, 0.355091027, 0.764863731, 0.904099543, 0.396109613, 0.817134856, 0.348974222,
        0.266193634, 0.367501958, 0.752316213, 0.587800024, 0.489421095, 0.673474061, 0.328296139, 0.853945839,
        0.832380736, 0.159588686, 0.322411022, 0.950173707, 0.095376712, 0.231019855, 0.860607752, 0.359627192,
        0.984843699,0.0319756679, 0.828649914,  0.51680949, 0.489407924, 0.963977298, 0.960131739, 0.681816791,
        0.860788169, 0.455829282, 0.332390656,0.0591498043, 0.452245977, 0.217354216,  0.34560744, 0.549971993,
        0.317622252, 0.892976443,  0.49004545,  0.25647901, 0.968998638, 0.910636465, 0.226717598, 0.327828572,
        0.28670209, 0.142515054,0.0992817392, 0.192332409, 0.308376869, 0.871415959, 0.391148786, 0.788660882,
        0.200816041, 0.986475959, 0.882862126, 0.109862451, 0.354283255, 0.555742682, 0.690698458, 0.643815752,
        0.363104285,0.0788627111, 0.200820414,  0.71697353, 0.744353746,  0.76763643, 0.245442451, 0.668009119,
        0.886989377, 0.366849931, 0.531556628, 0.502843979,  0.31454367, 0.622541364,0.0199038582, 0.676355134,
        0.429818622, 0.232835212, 0.987619457, 0.306572135, 0.494637038, 0.748614893, 0.891843561,0.0452854959,
        0.427561072, 0.226978442, 0.484072985,  0.16464563,0.0898074883, 0.384263737,0.0238354723, 0.329734547,
        0.531230736, 0.476683361, 0.877482474, 0.455501628, 0.497302495, 0.396184301, 0.886124728, 0.736070092,
        0.108917595, 0.397921902, 0.842575021,  0.82620032, 0.936655165,  0.24558961, 0.639688616, 0.493335031,
        0.0734495069, 0.780138101,0.0421121232, 0.701116477, 0.940523267,  0.70054817, 0.776760272, 0.192742581,
        0.0069252688, 0.842983626, 0.919324176, 0.242083269, 0.190100674, 0.735084639, 0.164522319,  0.99030645,
        0.98284794, 0.657169539,0.0187736442, 0.759596482, 0.357567611, 0.509016344, 0.738899681, 0.567923164,
        0.289056634,  0.41501714, 0.981054561, 0.365884479, 0.517878261, 0.844209022, 0.968122653, 0.258894528,
        0.478310441, 0.437340986, 0.379398001, 0.203081884, 0.550820748, 0.255542723, 0.550098031, 0.870477939,
        0.241230214, 0.157108238, 0.218260827, 0.116277737, 0.749018275, 0.158290659, 0.476353907, 0.545327323,
        0.878978121,0.0171442169, 0.542981987, 0.318018082, 0.788805343, 0.871721374, 0.738490409,0.0923330146,
        0.301398643, 0.637103286, 0.571564271, 0.712810342, 0.644289242, 0.230476008, 0.971695586, 0.966159428,
        0.291883909, 0.175285818, 0.312882552,  0.98465128, 0.568391354, 0.844468564, 0.144433908,  0.45994061,
        0.607897905, 0.184122705, 0.342805493, 0.606432998, 0.838196585, 0.186188518,0.0302744689, 0.307391858,
        0.125286029, 0.270394965, 0.874161481, 0.370509557,  0.89423337, 0.407995674, 0.881878469, 0.647951238,
        0.236986727, 0.528807336, 0.293731542,0.0943204253, 0.934538626, 0.121679332,  0.34968176,0.0670268578,
        0.642196769, 0.692447138, 0.334926733, 0.374244194, 0.313885051, 0.538738295, 0.098592523, 0.490514225,
        0.32873567, 0.709725794,  0.88169803, 0.393000481, 0.854243273, 0.463776593,  0.52705639, 0.493309892,
        0.267784336, 0.583077476,0.0573514167, 0.959336368, 0.771417173,0.0427184631, 0.498433369,0.0522942701,
        0.56155145, 0.960361909, 0.619817314, 0.528628368, 0.698235179, 0.186162042, 0.553998168, 0.666120292,
        0.152731049, 0.948750157, 0.186825789, 0.580512664, 0.851024442, 0.106865844, 0.675861737,  0.79604524,
        0.657646103,0.00934952381, 0.206267588, 0.636420368,0.0382564603,  0.67771025, 0.677917925, 0.671684269,
        0.396317716, 0.661597047, 0.633360383, 0.962124239, 0.992711418,0.0993448263,0.0678932741, 0.426013152,
        0.947045502, 0.708326009, 0.466817846,0.0448362886, 0.748580922, 0.678370694, 0.210921343, 0.398490306,
        0.953675585,0.0289022848, 0.935766569, 0.846930474, 0.662760176, 0.867910903, 0.652359324,  0.45280494,
        0.305228982, 0.352034987, 0.279643402, 0.236045594,0.0270034608, 0.652062389, 0.712000227, 0.619930867,
        0.125439078, 0.452789963,  0.92233151, 0.120844359, 0.403808975, 0.260290446, 0.778843638,   0.6678412,
        0.0267894373, 0.491332301, 0.915060888, 0.704025347, 0.628200853, 0.578338467, 0.629156416, 0.730410649,
        0.641318334, 0.463709335, 0.614291239, 0.254470656, 0.808682692,  0.22898373, 0.450477996, 0.874235142,
        0.202773906, 0.523711192, 0.126518266, 0.579402899,  0.26188467, 0.207769057,  0.55283816, 0.851395364,
        0.513594437, 0.558259845, 0.666148535, 0.998974657, 0.178274074, 0.116739636,0.0684255431, 0.622713377,
        0.31448295, 0.889827933,  0.80647766, 0.429916949, 0.524695458,  0.45267553, 0.630743121, 0.566594485,
        0.958860663, 0.908052286, 0.700898262, 0.377025384, 0.683796226, 0.198088462, 0.617400699, 0.413726158,
        0.823588417, 0.755577948, 0.703097317, 0.364294278, 0.819786986, 0.751581763, 0.048769509, 0.528569003,
        0.616748192, 0.270942831, 0.800841747, 0.235174223, 0.903786552, 0.258801569, 0.191336412, 0.012410342,
        0.853413998, 0.621008712, 0.855861931, 0.140106201, 0.872687964, 0.708839735,0.0926409892,0.0207504195,
        0.782636518,0.0300825236, 0.504610632,0.0816221782, 0.773493745, 0.872577282, 0.880031248, 0.883524299,
        0.872427328, 0.458722225, 0.902298841, 0.547904952,0.0559884352, 0.591179888, 0.563941709, 0.776130076,
        0.295569778,0.0408536533, 0.398567183,  0.28227462, 0.806716321, 0.507159362, 0.688150965,  0.49466404,
        0.45454604, 0.421480091,0.0392517329,0.0911962031, 0.393815309, 0.135373195, 0.968650583, 0.811676111,
        0.325965411, 0.961999178, 0.100281202, 0.102924612,  0.30725909,  0.33368206, 0.857966134, 0.522921736,
        0.615500041, 0.981558684, 0.797484739, 0.198809674,  0.45670419, 0.570970797, 0.214908696, 0.686433314,
        0.278602115, 0.179739848, 0.397497946, 0.162858935, 0.802621762,0.0836459133, 0.638270752, 0.230856518,
        0.580094379, 0.864292514, 0.932738287, 0.821393124, 0.480590473, 0.636373016, 0.181508656, 0.469200501,
        0.309276441, 0.668810431, 0.722341161, 0.574856669, 0.527854513, 0.809231559, 0.986882661, 0.323860496,
        0.606396459, 0.759558966,  0.79096818,0.0699298142, 0.550465414,0.00929828244, 0.784629475, 0.689044114,
        0.963588091, 0.516441598, 0.357178305, 0.482336892, 0.429959602, 0.996306147, 0.601176011, 0.785004207,
        0.970542121, 0.487854549,0.0949267522, 0.979331773, 0.120877739, 0.630260336,  0.19424754, 0.213081703,
        0.0145987798, 0.366671115, 0.340100777, 0.721786347, 0.367533113,0.0210335371, 0.131687992, 0.586759676,
        0.73360464, 0.863635151, 0.136994646,0.0524269778, 0.406223408, 0.241656947, 0.472450703, 0.872215979,
        0.454719233,0.0715790696, 0.314061244, 0.492823114, 0.741721134, 0.694783663, 0.982867872, 0.319748137,
        0.804203704,0.0534678153, 0.746155348, 0.303474931,0.0930815139, 0.934531664, 0.746868186, 0.100048471,
        0.720296508,  0.21075374,  0.96309675, 0.749189411, 0.739621932, 0.510072327,0.0872929865, 0.650020469,
        0.0823648495, 0.726920745, 0.532618265, 0.749305866,  0.86126694,0.0346994482,0.0931224583, 0.655257095,
        0.959517847, 0.487057231, 0.859895745, 0.084794421, 0.718541715, 0.850918328, 0.818884782,  0.71627446,
        0.40822393,  0.63658567, 0.523838703, 0.372038872, 0.353426097, 0.598049047,0.0974868746, 0.276353038
     };

     Int_t rc1 = 0;
     Int_t rc2 = 0;
     TRandom3 r(4357);
     Float_t x;
     Int_t i;

     // check whether the sequence is ok or not
     for (i=0;i<1000;i++) {
       x = r.Rndm();
       // printf("%e ",x-RefValue[i]); if(i%8==7) printf("\n");
       if (TMath::Abs(x-RefValue[i]) > 10e-8) {
         printf("i=%d x=%.8f but should be %.8f\n",i,x,RefValue[i]);
         rc1 += 1;
       }
     }

     // check whether a state can be saved and restored
     TFile *file = new TFile("random3.root","RECREATE");
     file->SetCompressionLevel(0);
     r.Write("r");
     delete file;
     file = new TFile("random3.root");
     TRandom3 *rs = (TRandom3*) file->Get("r");
     for (i=0;i<1000;i++) {
       if (r.Rndm() - rs->Rndm() != 0) rc2 += 1;
     }
     if (rc2 != 0) printf("state restoration failed\n");

     return rc1 + rc2;
}


void testrandom()
{
   testRandom3();
   testAll();
}
